#!/user/bin/env python
# -*- coding: utf-8 -*-
''' 
Author: Sjy
LastEditTime: 2024-11-01 14:28:08
Description: apps 为管理apps 的模块，主要用于管理apps 的加载和卸载
dapps/ 为apps 的模块
    www.carvecloud.com/ 为 域名模块（可以允许不同公司开发的内容放在一起，便于加载卸载）
        dblite/  为真正的程序模块
        ...

apps 模块描述
    一个具体的app 可能包含界面也可能不包含界面，按需求来定
    包含界面
        菜单，dock，工作区，状态栏，view工具
    不包含界面
        view 操作，计算库，数据库，等
模块原则：
    不允许限制其他模块的功能，但是可以提供接口
    不允许修改其他模块的数据，但是可以提供接口
    不允许修改其他模块的界面，但是可以提供接口
    不允许修改其他模块的配置，但是可以提供接口


状态：
    安装，初次安装模块
        自动按当前路径作为key索引字符串，保存到已安装的模块列表中
        config/apps/installed.json 
            [
                {
                    "title": "数智化软件",
                    "version": "0.0.1",
                    "name": "aircraft", 
                    "companyId": "carvecloud",
                    "docks":[ // 安装的dock列表 注意会根据此列表内容动态卸载已经安装过的dock
                        "plugins.carvecloud.aircraft.dock"
                    ]
                }
            ]
    卸载，把安装的模块卸载删除
        从 config/apps/installed.json 中删除对应的模块信息 通过 模块的company 和 name 来索引 删除
        将模块整体删除
    初始化 
        在安装后会立即初始化调用，
        当主程序启动时，会按顺序执行各个模块的初始化函数
'''

__all__= []

import traceback
import os
import sys
import importlib.machinery
import os.path

import gui.components.utils as utils
import gui.components.util_file as UFile
import gui.items.plugin as PG


global CONFIG_PLUGIN_PATH
CONFIG_PLUGIN_PATH = "config/plugins/"
global PATH_PLUGIN 
PATH_PLUGIN = "plugins"

global _CONFIG 
_CONFIG = {}

global __PLUGIN_INS
__PLUGIN_INS = {}

def init() -> None:
    """初始化
    """
    init_config_data()
    init_installed_plugins()
    pass

def init_config_data() -> None:
    """
    初始化配置数据
    """
    global _CONFIG
    _CONFIG = {}
    for root, dirs, files in os.walk(CONFIG_PLUGIN_PATH):
        for file in files:
            fileExt = UFile.get_file_extesion(file)
            filename = UFile.get_file_name(file)
            if fileExt == ".json":
                try:
                    _CONFIG[filename] = UFile.open_json(os.path.join(root, file))
                except Exception as e:
                    print(e)
def init_installed_plugins() -> None:
    """
    初始化已安装的插件 就是调用插件中提供的init函数 
    配置数据格式为（当前）
        [
            {
                "title": "数智化软件",
                "version": "0.0.1",
                "name": "aircraft", 
                "companyId": "01"
            }
        ]
    """
    installeds = get_config_data("installed", [])
    for item in installeds:
        try:
            name = item.get('name') 
            companyId = item.get('companyId') 
            module = __import__(f"{PATH_PLUGIN}.{companyId}.{name}.main", fromlist=[""])
            # 每个模块在启动时要初始化
            moduleClasses = utils.get_all_subclasses(module, PG.Plugin)
            for module in moduleClasses:
                key = get_key(companyId, name, module)
                mod = module(item)
                add_key_ins(key, mod)
                # 继承此类的模块都会存在on_init函数 需要在程序启动时调用
                mod.on_init()
                
        except:
            traceback.print_exc()

def get_config_data(name:str=None, defValue:any=None) -> any:
    """获取指定文件的配置数据

    Args:
        name (str, optional): 文件名（不包含后缀）. Defaults to None.
        defValue (any, optional): 数据的缺省值. Defaults to None.

    Returns:
        any: 返回数据
    """
    try:
        return _CONFIG[name]
    except KeyError:
        return defValue
def get_key(companyId:str=None, name:str=None, module:PG.Plugin=None) -> str:
    """获取实例key
    Args:
        name (str): 安装时生成的名字
        module (PG.Plugin): 继承的类模块
    Returns:
        str: 返回组合的类名
    """
    return f"{companyId}:{name}({module.__name__})"
def add_key_ins(name:str=None, pluginIns:PG.Plugin=None) -> None:
    """添加实例管理
    Args:
        name (str, optional): key索引. Defaults to None.
        pluginIns (PG.Plugin, optional): 实例. Defaults to None.
    """
    global __PLUGIN_INS
    __PLUGIN_INS[name] = pluginIns


def get_plugin_installs() -> list:
    """获取全部的插件信息
    Args:
        无
    Returns:
        list: 返回数据列表
    """
    